package com.gz.spring.aop.aspectj;

import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.Signature;
import org.aspectj.lang.annotation.*;
import org.junit.jupiter.api.Order;
import org.springframework.stereotype.Component;

import java.lang.reflect.Method;
import java.util.Arrays;

/**
 * 切面类
 * 1.@Before 表示前置通知，即在目标方法执行前执行
 * 2.value = "execution(public float com.gz.spring.aop.aspectj.Func.getSub(float,float))"
 * 3.指定切入到哪个类的哪个方法
 * 4.f1方法，程序员可以自己指定方法名，一般叫showBeginLog
 * 5.JoinPoint joinPoint 在底层执行时，由AspectJ切面框架，会给该切入方法传入JoinPoint对象，
 * 通过该方法，可以获取到相关信息如(Object proxy, Method method, Object[] args)
 */
@Order(1) //如果还有其他切面类，用order可以规定执行顺序(order值越小，优先级越高)
@Aspect //表示是一个切面类
@Component
public class FuncAspect {

    //切入点表达是(用来提高复用性)
    //例如execution(public float com.gz.spring.aop.aspectj.Func.getSub(float,float))
    //可以替换成myPointCut()
    @Pointcut(value = "execution(public float com.gz.spring.aop.aspectj.Func.getSub(float,float)) ||"+
            "execution(public float com.gz.spring.aop.aspectj.Func.getSum(float,float))")
    public void myPointCut() {}

    //前置通知
//    @Before(value = "execution(public float com.gz.spring.aop.aspectj.Func.getSub(float,float))")
    //如果在同一个类，可以简写成"execution(public float Func.getSub(float,float))"
    @Before(value = "myPointCut()")
    public  void showBeginLog(JoinPoint joinPoint) {
        Signature signature = joinPoint.getSignature();
        System.out.println("切面类的showBeginLog-方法执行前-日志-方法名-" +signature.getName()+
                "-参数"+ Arrays.toString(joinPoint.getArgs()));//从AOP看，这里是一个横切关注点-前置通知
    }

    //返回通知
//    @AfterReturning(value = "execution(public float com.gz.spring.aop.aspectj.Func.getSub(float,float))")
    @AfterReturning(value = "myPointCut()"
            ,returning = "res")
    public  void showSuccessEndLog(JoinPoint joinPoint,Object res) {
        Signature signature = joinPoint.getSignature();
        System.out.println("切面类的showSuccessEndLog-方法正常使用结束-日志-方法名-"+
                signature.getName()+"-执行结果="+res);//从AOP看，也是一个横切关注点-返回通知
    }

    //异常通知
//    @AfterThrowing(value = "execution(public float com.gz.spring.aop.aspectj.Func.getSub(float,float))")
    @AfterThrowing(value = "myPointCut()",throwing = "e")
    public  void showExceptionLog(JoinPoint joinPoint,Exception e) {
        Signature signature = joinPoint.getSignature();
        System.out.println("切面类的showExceptionLog-方法出现异常-日志-方法名-"+signature.getName()
                +"-异常信息="+e);//从AOP看，也是一个横切关注点-异常通知
    }

    //最终通知
//    @After(value = "execution(public float com.gz.spring.aop.aspectj.Func.getSub(float,float))")
    @After(value = "myPointCut()")
    public  void showFinallyEndLog(JoinPoint joinPoint){
        Signature signature = joinPoint.getSignature();
        System.out.println("切面类的showFinallyEndLog-方法最终执行完毕-日志-方法名-"+signature.getName());//从AOP看，也是一个横切关注点-最终通知
    }
}
